<?php
/**
 * Created by PhpStorm.
 * User: My
 * Date: 2018/9/3
 * Time: 15:42
 */

namespace App\Http\Helper;

use App\Exceptions\UserException;
use App\Models\LogHelper;
use App\Services\Algo\FiveDimensionTestingAlgo;
use App\Services\OpensslEncryptHelper;
use TestingDetailService;
use TestingPartService;
use TestingPartRecordService;
use WechatUserService;
use TestingItemService;
use TestingAlgoHelper;
use TestingConfig;
use DB;
use UserRecordService;
use JzNutritionistService;
use TestingChannelService;
use TestingSyncOrderService;

class FiveDimensionalHelper
{
    /**
     * 获取五维测评的题目信息
     * @param $uid
     * @param $tid
     * @param $type
     * @param $orderId
     * @param $nutriId
     * @return array
     */
    public static function fiveDimensionAssessment($uid, $tid, $type, $orderId, $nutriId) {
        $data = [
            'dimension' => [],
            'result' => [],
            'final_result' => [],
            'question_list' => [],
            'channel' => '',
            'page_type' => 1,
            'pop' => [
                'show_pop' => 0
            ]
        ];

        $partRecord = TestingPartRecordService::getLastOneByUid($uid, $tid);
        $maxDimension = TestingPartService::getMaxDimensionByTid($tid);

        if ($partRecord && $partRecord['dimension'] < $maxDimension) {
            $dimension = TestingPartService::getOneByTidAndDimension($tid, $partRecord['dimension'] + 1);
            //获取当前维度的结果信息
            $resultData = json_decode($partRecord['result'], true);
            $data['result'] = $resultData['result'];
            $data['dimension'] = $dimension ? self::formatDimension($dimension) : [];
            //取出下一维度的题目
            $data['question_list'] = self::getDimensionInfo($tid, $data['dimension']);

            return $data;
        } else {
            $user = WechatUserService::getByUid($uid);
            if (!$user) {
                $user = [
                    'channel_code' => '',
                    'uid' => $uid,
                ];
            }
            if ($tid == BusinessHelper::getDimensionPayTid() && $nutriId && $type != 'retry') {
                //付费且带有营养师，则判断是否有在这个营养师下的做的测评，没有就要重做
                $userRecord = UserRecordService::getLastOneByUidTidNutriId($uid, $tid, $nutriId);
                if ($userRecord) {
                    $resultData = json_decode($partRecord['result'], true);
                    $data['result'] = $resultData['result'];
                    $data['final_result'] = $resultData['final_result'];

                    //根据渠道指定页面
                    list($pageType, ) = self::getPageType($user['channel_code'], $tid);
                    $data['page_type'] = $pageType;

                    return $data;
                }
            } elseif ($partRecord && $type != 'retry') {
                //存在记录，且不是重做
                $resultData = json_decode($partRecord['result'], true);
                $data['result'] = $resultData['result'];
                $data['final_result'] = $resultData['final_result'];

                //根据渠道指定页面
                list($pageType, ) = self::getPageType($user['channel_code'], $tid);
                $data['page_type'] = $pageType;

                return $data;
            }

            //判断是否弹窗
            list($isPop, $usePop) = self::popType($user);
            if ($isPop) {
                $data['pop']['show_pop'] = $usePop;
            }

            $dimension = TestingPartService::getOneByTidAndDimension($tid, 1);
            $data['dimension'] = $dimension ? self::formatDimension($dimension) : [];
            //取出第一维度的题目信息
            $data['question_list'] = self::getDimensionInfo($tid, 1);

            return $data;
        }
    }

    /**
     * 获取测评结果信息
     * @param $uid
     * @param $tid
     * @return array
     */
    public static function fiveDimensionResult($uid, $tid) {
        $data = [
            'result_type' => 1,
            'final_result' => [],
            'risk_prediction' => [],
            'shop_mall' => [],
            'stature' => [],
            'part3_info' => [],
            'redirect_index' => 0
        ];

        $partRecord = TestingPartRecordService::getLastOneByUid($uid, $tid);
        $maxDimension = TestingPartService::getMaxDimensionByTid($tid);

        if ($partRecord['dimension'] != $maxDimension) {
            return [false, 'five_dimension.dimension_error'];
        }

        $resultData = json_decode($partRecord['result'], true);
        $data['final_result'] = $resultData['final_result'];
        $data['risk_prediction'] = $resultData['risk_prediction'];
        //第三部分的内容
        self::getPart3Info($uid, $tid, $resultData, $data);

        return [true, $data];
    }

    /**
     * 提交用户的答题信息
     * @param $uid
     * @param $tid
     * @param $orderId
     * @param $nutriId
     * @param $dimension
     * @param $answers
     * @return array|bool
     */
    public static function submitFiveDimension($uid, $tid, $orderId,$virtualOrderId, $nutriId, $dimension, $answers) {
        if ($uid && $tid && $dimension && $answers) {
            $data = $partRecordRes = [];  // $data-插入user_record数据库的值 $partRecordRes-插入到part_record的记录的值  $res-函数返回的值
            //$res['popup'] = [];
            $partRecord = TestingPartRecordService::getLastOneByUid($uid, $tid);
            $maxDimension = TestingPartService::getMaxDimensionByTid($tid);

            if (!self::checkDimension($partRecord, $dimension, $maxDimension)) {
                LogHelper::log("用户答题维度异常 uid => " . $uid . ' tid => ' . $tid);
                return [false, 'five_dimension.dimension_error'];
            }

            if (!$testingInfo = TestingDetailService::getById($tid)) {
                return [false, 'eid_tid_not_match'];
            }

            $currentPart = TestingPartService::getOneByTidAndDimension($tid, $dimension);
            if ($dimension + 1 <= $maxDimension) {
                $nextPart = TestingPartService::getOneByTidAndDimension($tid, $dimension + 1);
            }
            $partRecordRes['answers'] = $answers;
            $partRecordRes['uid'] = $uid;
            $partRecordRes['tid'] = $tid;
            $partRecordRes['dimension'] = $dimension;
            $partRecordRes['evaluation_times'] = $dimension != 1 ? $partRecord['evaluation_times'] : ($partRecord ? $partRecord['evaluation_times'] + 1 : 1);
            //计算了当前维度的结果信息
            $result = self::calcResult($answers, $tid, $dimension, $uid, $partRecord['evaluation_times']);
            $partRecordRes['final_answers'] = $result['final_answer'];
            $res['result'] = $partRecordRes['result']['result'] = [
                'prefix' => $result['prefix'],
                'star_level' => $result['star_level'],
                'text' => $result['text'],
                'current_dimension_name' => $currentPart['name'],
                'next_dimension_name' => isset($nextPart) ? $nextPart['name'] : '',
            ];

            //$res['popup'] = $result['popup'];        //是否一直需要弹出，不谈就放到外面去，不保存
            if (isset($result['height'])) {
                $res['result']['height'] = $partRecordRes['result']['result']['height'] = $result['height'];
                $res['result']['weight'] = $partRecordRes['result']['result']['weight'] = $result['weight'];
                $res['result']['bmi_calc'] = $partRecordRes['result']['result']['bmi_calc'] = $result['bmi_calc'];
            }

            //用户完成五维答题
            if ($dimension == $maxDimension) {
                $typeFourExpress = TestingItemService::typeFourItem($tid);
                $typeFourExpress = empty($typeFourExpress) ? null : $typeFourExpress;

                //把测评的结果拼起来
                $hisAnswers = '';
                $partRecords = TestingPartRecordService::getByUidAndTimes($uid, $tid, $partRecord['evaluation_times']);
                foreach ($partRecords as $partRecordItem) {
                    if ($partRecordItem['dimension'] == 1) {
                        $hisAnswers = $partRecordItem['answers'];
                    } else {
                        $hisAnswers .= '##' . $partRecordItem['answers'];
                    }
                }
                $answers = $hisAnswers . '##' . $answers;

                //计算测评的结果
                $result = TestingAlgoHelper::calculate($tid, $answers, $typeFourExpress);

                if ($tid == BusinessHelper::getDimensionPayTid() && !$orderId && !$nutriId) {
                    list($orderId, $nutriId) = self::getUserInfo($uid);
                }

                $data['answers'] = $answers;
                $data['uid'] = $uid;
                $data['order_id'] = $orderId;
                $data['nutritionist_id'] = $nutriId;

                $nickName = WechatUserService::getNickNameByUid($uid);
                //$nickName = urldecode(base64_decode($nickName));
                $data['nick_name']= $nickName;
                $data['testing_name'] = TestingDetailService::getNameByTid($tid);
                $data['tid'] = $tid;

                $data['score'] = $result['totalScore'];
                $data['final_answers'] = $result['finalAnswerStr'];
                $data['conclusion'] = TestingAlgoHelper::getConclusion($data['tid'], $data['score'], $data['answers'], '', $typeFourExpress);
                $data['testtime'] = time();
                if($virtualOrderId){
                    $data['virtual_oid'] = $virtualOrderId;
                }

                $answerArr = DataTransHelper::convertAnswer($data['final_answers']);
                $fiveDimensionConfig = json_decode(TestingConfig::getValue('five.dimension.config', '{}'), true);
                //获取最终结果信息
                $partRecordRes['result']['final_result'] = self::getFinalResult($partRecords, $fiveDimensionConfig);
                $partRecordRes['result']['final_result']['score'] = $data['score'];
                //获取风险预测信息
                $partRecordRes['result']['risk_prediction'] = self::getRiskPrediction($answerArr, $fiveDimensionConfig);
                //获取商城的信息
                $partRecordRes['result']['shop_mall'] = self::getShopMall($answerArr, $fiveDimensionConfig);
                //获取用户的身材概述
                $partRecordRes['result']['stature'] = self::getStature($answerArr, $tid);
                //答案里面的信息, 不变的，配置的信息，读配置
                $partRecordRes['result']['answer_info'] = self::getAnswerInfo($answerArr);

                //记录测评结果和部分结果
                DB::transaction(function () use ($data, $partRecordRes, $tid, $uid,$virtualOrderId) {
                    $saveResult = UserRecordService::stroeResult($data);
                    if($virtualOrderId){
                        LogHelper::log('通知结果回调===>virtual_oid:'.$virtualOrderId);
                        UserRecordService::syncVirtualOrderRecord($saveResult);
                    }

                    TestingDetailService::updataTestTimes($data['tid']);

                    //记录部分测评结果信息
                    $partRecordRes['result'] = json_encode($partRecordRes['result']);
                    TestingPartRecordService::store($partRecordRes);
                    //public的测评ID，检查是否需要转化为付费
                    if ($tid == BusinessHelper::getDimensionPublicTid()) {
                        list($result, $orderId, $nutritionistId) = self::publicToPrivate($uid);
                        if ($result) {
                            // 测评直接转好了，需要同步到减脂
                            $uri = TestingConfig::getValue('jz.admin.base.url');
                            $params = [
                                'nutritionist_id' => $nutritionistId,
                                'order_id' => $orderId,
                                'tid' => $tid,
                                'uid' => $uid,
                                'nick_name' => $data['nick_name']
                            ];
                            $uri = $uri . '/service/jz/manage/clear/record?param=' . OpensslEncryptHelper::encryptWithOpenssl(json_encode($params));
                            curlRequest($uri, [], 'get');
                        }
                    }
                }, 5);
            } else {
                $dimension = TestingPartService::getOneByTidAndDimension($tid, $dimension + 1);
                $res['dimension'] = $dimension ? self::formatDimension($dimension) : [];
                //获取下一维度的题目信息
                $res['question_list'] = self::getDimensionInfo($tid, $dimension['dimension']);
                //记录部分测评结果信息
                $partRecordRes['result'] = json_encode($partRecordRes['result']);
                TestingPartRecordService::store($partRecordRes);
            }
            return [true, $res];
        } else {
            LogHelper::log('参数异常 uid ==> ' . $uid . ' tid ==> ' . $tid . ' dimension ==>' . $dimension . ' answer ==> ' . $answers);
            return [false, 'param_error'];
        }
    }

    /**
     * 获取第三部分的结果信息
     * @param $uid
     * @param $tid
     * @param $resultData
     * @param $data
     */
    protected static function getPart3Info($uid, $tid, $resultData, &$data) {
        $channelCode = WechatUserService::getUserChannelCode($uid);
        //根据渠道指定页面
        list($pageType, $redirect) = self::getPageType($channelCode, $tid);
        $data['result_type'] = $pageType;
        $data['redirect_index'] = $redirect;
        switch ($data['result_type']) {
            case 3:
                $data['part3_info'] = [
                    'channel' => $channelCode,
                    'data' => self::getCareLinker(formatArrValue($resultData, 'answer_info', []))
                ];
                break;
            case 2:
                $data['stature'] = formatArrValue($resultData, 'stature', []);
                break;
            case 1:
                $fiveDimensionConfig = json_decode(TestingConfig::getValue('five.dimension.config', '{}'), true);
                $data['shop_mall'] = self::getAllShopMall(formatArrValue($resultData, 'shop_mall', []), $fiveDimensionConfig);
                break;
            default:
                break;
        }
    }

    /**
     * 根据channelCode获取页面类型
     * @param $channelCode
     * @param $tid
     * @return array
     */
    protected static function getPageType($channelCode, $tid) {
        $channel = TestingChannelService::getOneByCode($channelCode);

        if ($channel && $channel['page_type']) {    //有渠道且配置了页面类型的，根据页面类型显示数据
            $pageType = json_decode($channel['page_type'], true);
            $pageType = isset($pageType[$tid]) ? $pageType[$tid] : 1;
            $config = json_decode($channel['config'], true);
            $redirect = isset($config['redirect_index']) ? $config['redirect_index'] : 0;
            return [$pageType, $redirect];
        } else {
            switch ($channelCode) {
                case Constant::CHANNEL_CARE_LINKER:
                    return [3, 0];
                default:
                    //付费测评显示身材概述
                    if (BusinessHelper::getDimensionPayTid() == $tid) {
                        return  [2, 0];
                    } else {
                        return  [1, 0];
                    }
            }
        }
    }

    /**
     * 获取最终结果的显示信息
     * @param $partRecords
     * @param $fiveDimensionConfig
     * @return array
     */
    protected static function getFinalResult($partRecords, $fiveDimensionConfig) {
        $data = [];
        foreach ($partRecords as $partRecord) {
            $result = json_decode($partRecord['result'], true);
            $part = TestingPartService::getOneByTidAndDimension($partRecord['tid'], $partRecord['dimension']);
            if (isset($part['alias_name'])) {
                $data['result'][] = [
                    'name' => $result['result']['prefix'],
                    'value' => $result['result']['star_level'],
                    'text' => $result['result']['text'],
                ];
            }
        }
        $data['dimension_name'] = isset($fiveDimensionConfig['initial_dimension']) ? $fiveDimensionConfig['initial_dimension'] : '';
        return $data;
    }

    /**
     * 获取风险预测的信息
     * @param $answers
     * @param $fiveDimensionConfig
     * @return array
     */
    protected static function getRiskPrediction($answers, $fiveDimensionConfig) {
        $data = [
            'x_axis' => [],
            'data' => [],
        ];
        $configs = [
            [
                'axis' => '糖尿病',
                'in_array' => 100,
                '@24,==0&&,@43,>=29' => [70, 80],
                '@24,==0&&,@43,>=24.5' => [45, 70],
                '@24,==0&&,@43,<24.5' => [15, 35],

                '@24,==1&&,@43,>=35' => [90, 95],
                '@24,==1&&,@43,>=29' => [70, 90],
                '@24,==1&&,@43,>=24.5' => [40, 69],
                '@24,==1&&,@43,<24.5' => [15, 30],
            ],
            [
                'axis' => '心脏病',
                'in_array' => [
                    ['心血管疾病', 100],
                    ['and', ['高血压', '高血脂'], [
                        '@43,>=29' => [70, 85],
                        '@43,>=24.5' => [45, 70],
                        '@43,<24.5' => [20, 45],
                    ]],
                    ['or', ['高血压', '高血脂'], [
                        '@43,>=29' => [60, 75],
                        '@43,>=24.5' => [35, 60],
                        '@43,<24.5' => [15, 35],
                    ]],
                    ['other', ['高血压', '高血脂'], [
                        '@43,>=29' => [50, 65],
                        '@43,>=24.5' => [25, 50],
                        '@43,<24.5' => [10, 25],
                    ]]
                ],
            ],
            [
                'axis' => '癌症',
                '@34,==20' => [50, 60],
                '@34,==10' => [30, 50],
                '@34,==5' => [20, 30],

                '@13,==8&&,@43,>=29' => [30, 50],
                '@13,==8&&,@43,>=24.5' => [20, 30],
                '@13,==8&&,@43,<24.5' => [10, 20],
                '@13,==5&&,@43,>=29' => [30, 45],
                '@13,==5&&,@43,>=24.5' => [20, 30],
                '@13,==5&&,@43,<24.5' => [5, 20],
            ],
            [
                'axis' => '呼吸疾病',
                '@27,==20&&,@43,>=29' => [45, 60],
                '@27,==20&&,@43,>=24.5' => [35, 45],
                '@27,==20&&,@43,<24.5' => [20, 35],

                '@27,==10&&,@43,>=29' => [45, 55],
                '@27,==10&&,@43,>=24.5' => [25, 40],
                '@27,==10&&,@43,<24.5' => [15, 25],

                '@27,<10&&,@43,>=29' => [30, 45],
                '@27,<10&&,@43,>=24.5' => [20, 30],
                '@27,<10&&,@43,<24.5' => [10, 20],
            ],
            [
                'axis' => '记忆力衰退',
                '@43,>=29' => [45, 60],
                '@43,>=24.5' => [30, 45],
                '@43,<24.5' => [10, 30],
            ],
            [
                'axis' => '骨骼肌肉疾病',
                '@14,==8&&,@43,>=29' => [60, 80],
                '@14,==8&&,@43,>=24.5' => [45, 60],
                '@14,==8&&,@43,<24.5' => [25, 30],

                '@14,!=8&&,@43,>=29' => [50, 65],
                '@14,!=8&&,@43,>=24.5' => [25, 50],
                '@14,!=8&&,@43,<24.5' => [10, 25],
            ]
        ];

        $value33Arr = explode('|||', self::getValue($answers, 33, 'answer'));
        foreach ($configs as  $key => $config) {
            array_push($data['x_axis'], $config['axis']);
            foreach ($config as $key2 => $value) {
                if ($key2 == 'axis') {
                    continue;
                }
                if ($key2 == 'in_array') {
                    if (is_array($value)) {
                        $currentValue = [];
                        foreach ($value as $key3 => $value3) {
                            if (in_array($value3[0], ['and', 'or', 'other'])) {
                                switch ($value3[0]) {
                                    case 'and':
                                        $flag = true;
                                        foreach ($value3[1] as $value5) {
                                            if (!in_array($value5, $value33Arr)) {
                                                $flag = false;
                                                break;
                                            }
                                        }
                                        $currentValue = $flag ? $value3[2] : [];
                                        break;
                                    case 'or':
                                        foreach ($value3[1] as $value5) {
                                            if (in_array($value5, $value33Arr)) {
                                                $currentValue = $value3[2];
                                                break;
                                            }
                                        }
                                        break;
                                    default:
                                        $currentValue = $value3[2];
                                        break;
                                }
                            } else {
                                if (in_array($value3[0], $value33Arr)) {
                                    $isBreak3 = true;
                                    array_push($data['data'], $value3[1]);
                                    break;
                                }
                            }

                            if ($currentValue) break;
                        }
                        if (isset($isBreak3) && $isBreak3 == true) {
                            break;
                        }
                        if ($currentValue) {
                            $isBreak4 = false;
                            foreach ($currentValue as $key4 => $value4) {
                                $isTrue = self::getExpressionResult($answers, $key4);
                                if ($isTrue) {
                                    $isBreak4 = true;
                                    array_push($data['data'], rand($value4[0], $value4[1]));
                                    break;
                                }
                            }
                            if ($isBreak4) {
                                break;
                            }
                        }
                    } else {
                        if (in_array($configs[$key]['axis'], $value33Arr)) {
                            array_push($data['data'], $value);
                            break;
                        }
                    }
                } else {
                    $isTrue = self::getExpressionResult($answers, $key2);
                    if ($isTrue) {
                        array_push($data['data'], rand($value[0], $value[1]));
                        break;
                    }
                }
            }
        }

        return [
            'bar_data' => $data,
            'conclusion' => isset($fiveDimensionConfig['risk_pre']) ? $fiveDimensionConfig['risk_pre'] : [], //'根据您的评测，上述疾病是您需要特别关注的预防重于诊治，请有针对性的调整自己的饮食运动与作息。'
        ];
    }

    /**
     * 获取商城的各种信息
     * @param $answers
     * @param $fiveDimensionConfig
     * @return array
     */
    protected static function getShopMall($answers, $fiveDimensionConfig) {
        $reachConfig = json_decode(TestingConfig::getValue('five.dimension.lose_weight.reach', '{}'), true);
        $textConfig = json_decode(TestingConfig::getValue('five.dimension.lose_weight.tips', '{}'), true);
        $value37 = self::getValue($answers, 37, 'answer');
        $value36 = self::getValue($answers, 36, 'answer');
        $reachRate = $value36 / $value37;

        $reachRateArr = self::getValueByArray($reachConfig, $reachRate, [50, 59]);
        $text = self::getValueByArray($textConfig, $value36, '');

        return [
            'expect' => $value37 . '周',
            'lose_weight' => $value36 . 'KG',
            'reach_rate' => rand($reachRateArr[0], $reachRateArr[1]),
            'text' => isset($fiveDimensionConfig['shop_mall']) ? array_merge($fiveDimensionConfig['shop_mall'], [$text]) : '',//'',
        ];
    }

    /**
     * 获取所有的商品页信息
     * 把商品配置项里面的东西改成动态的了
     * @param $shopMall
     * @param $fiveDimensionConfig
     * @return array
     */
    protected static function getAllShopMall($shopMall, $fiveDimensionConfig) {
        $nutritionImages = [];
        $nutritionList = JzNutritionistService::getPayNutritionList();
        foreach ($nutritionList as $nutrition) {
            $info = json_decode($nutrition['nutrition_info'], true);
            $nutritionImages[] = [
                'src' => $info['nutrition_img'],
                'nutrition_id' => $nutrition['nutrition_id'],
                'nutrition_name' => $nutrition['name'],
                'url' => $info['detail_url'],
            ];
        }

        return $shopMall + [
            'product_images' => isset($fiveDimensionConfig['product_images']) ? $fiveDimensionConfig['product_images'] : '',
            'nutrition_images' => $nutritionImages,
        ];
    }

    /**
     * 获取第三部分的答案信息
     * @param $answers
     * @return array
     */
    protected static function getAnswerInfo($answers) {
        $reachConfig = json_decode(TestingConfig::getValue('five.dimension.lose_weight.reach', '{}'), true);
        $value37 = self::getValue($answers, 37, 'answer');
        $value36 = self::getValue($answers, 36, 'answer');
        $reachRate = $value36 / $value37;
        $reachRateArr = self::getValueByArray($reachConfig, $reachRate, [50, 59]);

        return [
            'expect' => $value37 . '周',
            'lose_weight' => $value36 . 'KG',
            'reach_rate' => rand($reachRateArr[0], $reachRateArr[1]),
        ];
    }

    /**
     * 获取蓝信康的第三部分信息
     * @param $answerInfo
     * @return array
     */
    protected static function getCareLinker($answerInfo) {
        $fiveDimensionCareLinker = json_decode(TestingConfig::getValue('five.dimension.care.linker', '{}'), true);

        return array_merge($answerInfo, [
            'text' => $fiveDimensionCareLinker['tips'],
            'product' => $fiveDimensionCareLinker['product'],
            'qrcode' => $fiveDimensionCareLinker['qrcode']
        ]);
    }

    /**
     * 获取身材概述信息
     * @param $answers
     * @param $tid
     * @return array
     */
    protected static function getStature($answers, $tid) {
        //付费测评身材概述
        $payStature = json_decode(TestingConfig::getValue('five.dimension.pay.stature', '{}'), true);
        $weight24 = self::getValue($answers, 24, 'weight');
        $answer13 = self::getValue($answers, 13, 'answer');
        $testingItem = TestingItemService::getItemsByTidAndIndex($tid, [13]);
        $itemAnswer = json_decode($testingItem[0]['options'], true);
        $key = 0;
        foreach ($itemAnswer as $key => $answer) {
            if (trim($answer13) == trim($answer['key'])) {
                break;
            }
        }

        return [
            'stature_img' => $payStature['img'][$weight24][$key],
            'stature_text' => $payStature['text'][$key],
        ];
    }

    /**
     * 计算当前维度的结果
     * @param $answers
     * @param $tid
     * @param $dimension
     * @param $uid
     * @param $times
     * @return array
     */
    protected static function calcResult($answers, $tid, $dimension, $uid, $times) {
        $data = [
            'final_answer' => '',
            'prefix' => '',
            'star_level' => 0,
            'text' => '',
            //'popup' => [],
        ];
        $config = self::getConfig($tid, $dimension);
        if (isset($config['index'])) {
            $items = TestingItemService::getItemsByTidAndIndex($tid, $config['index']);
        }

        if ($dimension != 1) {
            $partRecord = TestingPartRecordService::getOneByUidAndDimension($uid, $tid, $dimension - 1, $times);
        }

        $answers = isset($partRecord) ? $partRecord['final_answers'] . '##' . $answers : $answers;
        $score = $answersArr = '';
        if (isset($items)) {
            $testingAlgo = (new FiveDimensionTestingAlgo($tid, $answers, null, false));
            $score = $testingAlgo->calculateByExpression($items);
            $answers = $testingAlgo->resultToStr();
            $answersArr = $testingAlgo->getAllAnswer();
        }

//        if ($dimension == 4 && is_array($answersArr)) {
//            $value22 = self::getValue($answersArr, 22, 'answer');
//            $value23 = self::getValue($answersArr, 23, 'answer');
//            if ($value23 < ($value22 * $value22 * 18.5 / 10000)) {
//                $data['popup'] = json_decode(TestingConfig::getValue('five.dimension.popup1', '{}'), true);
//            }
//        }

        //维度信息
        $part = TestingPartService::getOneByTidAndDimension($tid, $dimension);
        $data['prefix'] = mb_substr($part['name'], 0, 2);
        $data['final_answer'] = $answers;
        if (is_numeric($score) && $config['judge']) {
            foreach ($config['judge'] as $key => $value) {
                if ($score <= $key) {
                    $data['star_level'] = $value['star'];
                    if ($dimension == 4 && is_numeric(strpos($value['text'], '%s'))) {
                        $bmi = self::getValue($answersArr, 43, 'weight');
                        $data['text'] = sprintf($value['text'], round($bmi, 2), 23.99);
                    } else {
                        $data['text'] = $value['text'];
                    }
                    break;
                }
            }
            //写死吧，再改写活
            if ($dimension == 4) {
                $bmi = self::getValue($answersArr, 43, 'weight');
                if ($bmi < 18.5) {
                    $data['star_level'] = 3;
                    $data['text'] = '您体重低于正常标准哟，减脂增肌，达到更高的精神状态才是您的当务之急。';
                }
            }
        }
        if ($dimension == 5 && is_array($answersArr)) {
            $data['height'] = self::getValue($answersArr, 22, 'answer');
            $data['weight'] = self::getValue($answersArr, 23, 'answer');
            $data['bmi_calc'] = self::getValue($answersArr, 44, 'weight');
        }

        return $data;
    }

    /**
     * 获取当前维度的题目信息
     * @param $tid
     * @param int $dimension
     * @return array
     */
    protected static function getDimensionInfo($tid, $dimension) {
        $data = [];
        $result =  TestingDetailService::getItem($tid);
        $part = TestingPartService::getOneByTidAndDimension($tid, $dimension);
        $itemIds = json_decode($part['testing_item_ids'], true);
        if($result){
            foreach ($result['questionList'] as $item) {
                if (in_array($item['index'], $itemIds)) {
                    $data[] = $item;
                }
            }
            return $data;
        }
        return $data;
    }

    /**
     * 判断用户答题的维度是否正常
     * @param array $partRecord 用户最新的答题记录
     * @param int $dimension 当前完成的维度
     * @param int $maxDimension 最大维度
     * @return bool
     */
    protected static function checkDimension($partRecord, $dimension, $maxDimension) {
        return ($dimension == 1 && (!$partRecord || ($partRecord && $partRecord['dimension'] == $maxDimension)))
            || $partRecord['dimension'] + 1 == $dimension;
    }

    /**
     * 获取维度的配置信息
     * @param $tid
     * @param $dimension
     * @return array|mixed
     */
    protected static function getConfig($tid, $dimension) {
        $config = [];
        $part = TestingPartService::getOneByTidAndDimension($tid, $dimension);
        if ($part) {
            $config = json_decode($part['config'], true);
        }
        return $config;
    }

    /**
     * 格式化维度信息
     * @param $dimension
     * @return array
     */
    protected static function formatDimension($dimension) {
        $config = json_decode($dimension['config'], true);
        return [
            'dimension' => $dimension['dimension'],
            'name' => $dimension['name'],
            'tips' => $config['tips'],
            'tid' => $dimension['tid'],
        ];
    }

    /**
     * 判断是否弹窗
     * @param $user
     * @return array
     */
    protected static function popType($user) {
        if (!TestingSyncOrderService::getOneByUid($user['uid'])) {
            $channel = TestingChannelService::getOneByCode($user['channel_code']);
            if ($channel) {
                $config = json_decode($channel['config'], true);
                if (isset($config['show_pop']) && $config['show_pop']) {
                    return [true, $config['show_pop']];
                }
            }
        }
        return [false, 0];
    }

    /**
     * 测评同步
     * @param $uid
     * @return array
     */
    protected static function getUserInfo($uid) {
        $syncOrder = TestingSyncOrderService::getOneByUid($uid);
        if (!$syncOrder) {
            LogHelper::log("不存在用户的同步信息 uid:" . $uid);
            return [null, null];
        }
//        if ($syncOrder['status'] != 0) {
//            LogHelper::log("用户测评信息已同步 uid:" . $uid);
//            return [null, null];
//        }
        return [$syncOrder['order_id'], $syncOrder['nutritionist_id']];
    }

    /**
     * 测评同步
     * @param $uid
     * @return array
     */
    protected static function publicToPrivate($uid) {
        $syncOrder = TestingSyncOrderService::getOneByUid($uid);
        if (!$syncOrder) {
            LogHelper::log("不存在用户的同步信息 uid:" . $uid);
            return [false, null, null];
        }
        if ($syncOrder['status'] != 0) {
            LogHelper::log("用户测评信息已同步 uid:" . $uid);
            return [false, null, null];
        }
        $result = UserRecordService::syncFreeOrderTestingToPurchase(
            $syncOrder['order_id'],
            $uid,
            $syncOrder['nutritionist_id'],
            BusinessHelper::getDimensionPublicTid(),
            BusinessHelper::getDimensionPayTid()
        );
        if ($result['status'] == 1) {
            LogHelper::log("用户测评信息同步成功 uid:" . $uid);
            TestingSyncOrderService::updateByUid($uid, ['status' => 1]);
            return [true, $syncOrder['order_id'], $syncOrder['nutritionist_id']];
        } else {
            LogHelper::log("测评信息同步 public -> private 失败 uid:" . $uid);
            return [false, null, null];
        }
    }

    /**
     * 从配置的数组中获取需要的值
     * 数组的key为临界值
     * @param $arr
     * @param $need
     * @param $default
     * @return mixed
     */
    private static function getValueByArray($arr, $need, $default) {
        foreach ($arr as $key => $value) {
            if (is_numeric($key)) {
                if ($need <= $key) {
                    return $value;
                }
            } else {
                return $value;
            }
        }
        return $default;
    }

    /**
     * 获取表达式的结果
     * @param $answers
     * @param $expression
     * @return bool
     */
    private static function getExpressionResult($answers,$expression) {
        $result = false;

        $calArr = explode(',', $expression);
        foreach($calArr as $k => $v){
            if(substr($v,0,1) == '@'){//获取权重并替换
                $index = (int)substr($v,1);
                $weight = self::getValue($answers, $index,'weight');
                $calArr[$k] = $weight;
            }
        }
        $expressionStr = implode('', $calArr);

        eval('$result=' . $expressionStr . ';');
        return $result;
    }

    /**
     * 获取相应题号的权重或者值
     * @param $answers
     * @param $index
     * @param $valueType
     * @return null
     */
    private static function getValue($answers,$index,$valueType){
        $value = null;
        foreach($answers as $k => $v){
            if($v['index'] == $index){
                $value = $answers[$k][$valueType];
            }
        }
        return $value;
    }
}